package dataStructure.sort;

import java.util.Comparator;
import java.util.PriorityQueue;

// 分类 -------------- 内部比较排序
// 数据结构 ---------- 数组
// 最差时间复杂度 ---- O(nlogn)
// 最优时间复杂度 ---- O(nlogn)
// 平均时间复杂度 ---- O(nlogn)
// 所需辅助空间 ------ O(1)
// 稳定性 ------------ 不稳定
public class HeapSort extends DataCrol {
    private void heapify(int A[], int i, int size) {  // 从A[i]向下进行堆调整
        int leftChild = 2 * i + 1;  // 左孩子索引
        int rightChild = 2 * i + 2; // 右孩子索引
        int max = i;                // 选出当前结点与其左右孩子三者之中的最大值
        if (leftChild < size && A[leftChild] > A[max])
            max = leftChild;
        if (rightChild < size && A[rightChild] > A[max])
            max = rightChild;
        if (max != i) {
            swap(A, i, max);        // 把当前结点和它的最大(直接)子节点进行交换
            heapify(A, max, size);  // 递归调用，继续从当前结点向下进行堆调整
        }
    }

    //建立大根堆过程
    // 58 55 93 61 61 29 68 00 22 07
    //             i
    // 58 55 93 61 61 29 68 00 22 07
    //          i           L  R
    // 58 55 93 61 61 29 68 00 22 07
    //       i        L  R
    // 58 55 93 61 61 29 68 00 22 07
    //    i     L  R                ->swap(i,L)
    // 58 61 93 55 61 29 68 00 22 07
    //          i           L  R
    // 58 61 93 55 61 29 68 00 22 07
    // i  L  R                      ->swap(i,R)
    // 93 61 58 55 61 29 68 00 22 07
    //       i        L  R          ->swap(i,R)
    // 93 61 68 55 61 29 58 00 22 07
    //                   i
    private void buildHeap(int A[], int size) { // 建堆，时间复杂度O(n)
        for (int i = size / 2 - 1; i >= 0; i--) // 从每一个非叶结点开始向下进行堆调整
            heapify(A, i, size);
    }


    public void heapSortOrigin(int[] array) {
        //原生实现大根堆
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>();
        int heapSize = array.length;
        for (int i = 0; i < heapSize; i++) maxHeap.offer(array[i]);
        while (heapSize > 0) {
            array[--heapSize] = maxHeap.poll();
        }
    }

    @Override
    public void sort(int[] array) {
        int heapSize = array.length;
        buildHeap(array, heapSize);    // 建立一个最大堆
        while (heapSize > 1) { // 堆（无序区）元素个数大于1，未完成排序
            // 将堆顶元素与堆的最后一个元素互换，并从堆中去掉最后一个元素
            // 此处交换操作很有可能把后面元素的稳定性打乱，所以堆排序是不稳定的排序算法
            swap(array, 0, --heapSize);
            heapify(array, 0, heapSize);     // 从新的堆顶元素开始向下进行堆调整，时间复杂度O(logn)

        }
//        heapSortOrigin(array);
    }

    public static void main(String[] args) {
        HeapSort heapSort = new HeapSort();
        int[] array = DataCrol.createRandomArray(10);
        DataCrol.print(array);
        heapSort.sort(array);
        DataCrol.print(array);
        heapSort.timeTest(10000000);
    }
}
